require 'xapian'

module Mil
  module Index
    # This class provides a search agent that can be used to
    # query the index database. Allowing the look up of files
    # addresses from index database through labeled and generic
    # searches.
    class Search
      OBJECT_NAME = 0
      CREATED = 1
      LAST_UPDATED = 2

      def initialize(opts = {})
	@path = opts[:database] if opts[:database]
      end

      # Used to open the connections to the Xapian Database.
      # If already initially open, reopen the database to ensure
      # that fresh representation of the database is used.
      def open(database='')
	@path ||= database

	if database.empty? and @db
	  @db.reopen
	else
	  _open(@path)
	end

	@open = true
      end

      def terms
	xap_terms = @db.allterms

	xap_terms.collect { |t|
	  case t.term
	    when /^I/
	      t.term.gsub(/^I/, 'address:')
	    when /^N/
	      t.term.gsub(/^N/, 'name:')
	    when /^S/
	      t.term.gsub(/^S/, 'namespace:')
	    when /^T/
	      t.term.gsub(/^T/, 'tag:')
	    else
	      t.term
	  end
	}
      end

      # Set the query to be issued to the Xapian Database.
      def query=(query)
	@query = @qp.parse_query(query,
                  Xapian::QueryParser::FLAG_BOOLEAN | Xapian::QueryParser::FLAG_LOVEHATE |
		  Xapian::QueryParser::FLAG_WILDCARD | Xapian::QueryParser::FLAG_SPELLING_CORRECTION)
      end

      # Get a friendly description of the set query.
      def query
	@query.description
      end

      # Fetch the results from the query.
      def results(start,count)
	@enquire.query = @query

	mset = @enquire.mset(start, count)

	mset.matches.collect { |m|
	  { :docid => m.docid,
	    :rank => m.rank + 1,
	    :percent => m.percent,
	    :document => m.document
	  }
	}
      end

      private
      def _open(database='')
	@db = Xapian::Database.new(@path)
	@enquire = Xapian::Enquire.new(@db)

	@stemmer = Xapian::Stem.new('english')

	@qp = Xapian::QueryParser.new()
	@qp.stemmer = @stemmer
	@qp.database = @db
	@qp.stemming_strategy = Xapian::QueryParser::STEM_SOME
	@qp.default_op = Xapian::Query::OP_AND

	@qp.add_boolean_prefix("address", "I")
	@qp.add_boolean_prefix("name", "N")
	@qp.add_boolean_prefix("namespace", "S")
	@qp.add_boolean_prefix("tag", "T")

      end

    end
  end
end
